//因为服务器多进程，故需要保存token到全局，其他参见wechat-api文档
const chalk = require('chalk');
// const WechatAPI = require('wechat-api');
const WechatAPI = require('wechat-api');
const xml2js = require('xml2js');
const fs = require('fs');
const path = require('path');
const request = require('request');
const superagent = require('superagent');
const crypto = require('crypto');
const tenpayApi = require('./tenpay')
const {
    wConfig,
    cConfig
} = require('../config.js')
// https://github.com/lazing/wechat-api
// http://doxmate.cool/node-webot/wechat-api/api.html#api_user_exports_getUser
var menu = {
    "button": [{
        "name": "父按钮",
        "sub_button": [{
            "type": "view",
            "name": "子按钮",
            "url": "http://www.baidu.com"
        }, {
            "type": "view",
            "name": "子按钮",
            "url": "http://www.baidu.com"
        }, {
            "type": "view",
            "name": "子按钮",
            "url": "http://www.baidu.com"
        }]
    }, {
        "name": "父按钮",
        "sub_button": [{
            "type": "view",
            "name": "子按钮",
            "url": "http://www.baidu.com"
        }, {
            "type": "view",
            "name": "子按钮",
            "url": "http://www.baidu.com"
        }]
    }, {
        "name": "父按钮",
        "sub_button": [{
            "type": "view",
            "name": "关于我",
            "url": "http://www.baidu.com"
        }, {
            "type": "view",
            "name": "遇到我",
            "url": "http://www.baidu.com"
        }, {
            "type": "view",
            "name": "联系我们",
            "url": "http://www.baidu.com"
        }]
    }]
}
var api = new WechatAPI(wConfig.appID, wConfig.appsecret);

exports.initWechatApi = function () {
    //创建菜单
    /*  api.createMenu(menu, function (err, result) {
         if (err) {
             console.log('error', err);
         }
         console.log(chalk.redBright('create menu success'));
     });
     api.getAccessToken(function (err, token) {
         console.log(err);
         console.log(chalk.bgCyan(JSON.stringify(token)));
     }); */
}
exports.WECHATAPI = api;


class WechatAPIS {
    constructor(config) {
        this.appId = config.appID;
        this.appSecret = config.appsecret;
    }
    getAccessToken() {
        return new Promise((resolve, reject) => {
            try {
                let result = global.cache.get('wechatToken');
                resolve(result.access_token);
            } catch (error) {
                reject(error)
            }
        })
    }
    getTicket() {
        return new Promise((resolve, reject) => {
            try {
                let result = global.cache.get('wechatToken');
                resolve(result.ticket);
            } catch (error) {
                reject(error)
            }
        })
    }
    // 获取用户信息 不包含subscribe
    getUserInfo(openid, accessToken) {
        return new Promise(async (resolve, reject) => {
            let url = `https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openid}&lang=zh_CN`;
            try {
                let res = await superagent.get(url);
                resolve(res.body);
            } catch (error) {
                reject(error);
            }
        })
    }
    // 获取用户基础信息 包含subscribe
    getBaseInfo(openid) {
        return new Promise(async (resolve, reject) => {
            let accessToken = await this.getAccessToken();
            // let accessToken = await
            let url = `https://api.weixin.qq.com/cgi-bin/user/info?access_token=${accessToken}&openid=${openid}&lang=zh_CN`;
            try {
                let res = await superagent.get(url);
                resolve(res.body);
            } catch (error) {
                reject(error);
            }
        })
    }
    // 查询订单
    orderQuery(orderId) {
        return new Promise(async (resolve, reject) => {
            let url = 'https://api.mch.weixin.qq.com/pay/orderquery';
            let opt = {
                appid: cConfig.appid,
                mch_id: cConfig.mch_id,
                out_trade_no: orderId,
                nonce_str: this._get_nonce_str(32)
            };
            let arr = Object.keys(opt).sort().map(item => {
                return `${item}=${opt[item]}`;
            });
            // 这里拼接签名字符串的时候一定要注意: 商户的key是要单独拿出来拼在最后面的
            let str = arr.join('&') + '&key=' + cConfig.mch_key;
            opt.sign = this._getSign(str);
            const getOrder = (obj) => {
                let xml = this._json2xml(obj);
                return new Promise((resolve, reject) => {
                    // 这里用了reques库,不熟悉的同学可以看看相关文档 https://github.com/request/request
                    // 总之就是向微信的统一下单接口提交一个xml
                    request({
                        method: 'POST',
                        url,
                        body: xml
                    }, (err, res, body) => {
                        if (err) {
                            reject(err);
                        } else {
                            //如果成功即可得到微信返回参数
                            let obj = this._parseXml(body).xml;
                            resolve(obj);
                        }
                    });
                });
            }
            let res = await getOrder(opt);
            resolve(res);
        })
    }
    // 退款
    refund(orderId, out_refund_no, total_fee, refund_fee) {
        return new Promise(async (resolve, reject) => {
            let opt = {
                appid: cConfig.appid,
                mch_id: cConfig.mch_id,
                nonce_str: this._get_nonce_str(32),
                out_refund_no, //商户退款单号
                out_trade_no: String(orderId),
                total_fee: Number(total_fee),
                refund_fee: Number(refund_fee)
            };
            let arr = Object.keys(opt).sort().map(item => {
                return `${item}=${opt[item]}`;
            });
            // 这里拼接签名字符串的时候一定要注意: 商户的key是要单独拿出来拼在最后面的
            let str = arr.join('&') + '&key=' + cConfig.mch_key;
            opt.sign = this._getSign(str);
            const getRefund = (obj) => {
                let xml = this._json2xml(obj);
                return new Promise((resolve, reject) => {
                    // 这里用了reques库,不熟悉的同学可以看看相关文档 https://github.com/request/request
                    // 总之就是向微信的统一下单接口提交一个xml
                    let url = 'https://api.mch.weixin.qq.com/secapi/pay/refund'
                    request({
                        method: 'POST',
                        url,
                        body: xml,
                        agentOptions: {
                            pfx: fs.readFileSync(path.resolve(__dirname, './zhengshu/apiclient_cert.p12')),
                            passphrase: Buffer.from(String(cConfig.mch_id))
                        }
                    }, (err, res, body) => {
                        if (err) {
                            reject(err);
                        } else {
                            //如果成功即可得到微信返回参数
                            let obj = this._parseXml(body).xml;
                            console.log(obj);
                            resolve(obj);
                        }
                    });
                });
            }
            let res = await getRefund(opt);
            resolve(res);
        })
    }
    _json2xml(obj) {
        /**
     * 转化xml用了xml2js库
     https://github.com/Leonidas-from-XIV/node-xml2js
     * @param {Object} obj
     */
        let builder = new xml2js.Builder({
            headless: true,
            allowSurrogateChars: true,
            rootName: 'xml',
            cdata: true
        });
        var xml = builder.buildObject(obj);
        return xml;
    }
    _parseXml(xml) {
        let {
            parseString
        } = xml2js;
        let res;
        parseString(xml, {
            trim: true,
            explicitArray: false
        }, function (err, result) {
            res = result;
        });
        return res;
    }
    _get_nonce_str(len) {
        /**
         * 生成指定长度的随机数
         * @param {*int} len
         */
        let str = '';
        while (str.length < len) {
            str += Math.random().toString(36).slice(2);
        }
        return str.slice(-len);
    }
    _getSign(str) {
        /**
         * 对指定字符串进行md5加密
         * @param {String} str
         */
        let hash = crypto.createHash('md5').update(str, 'utf8');
        return hash.digest('hex').toUpperCase();
    }
}
exports.wechatAPIS = new WechatAPIS(wConfig);
//#region
/* var menu = {
    "button": [{
            "type": "click",
            "name": "ياسىلىۋاتىدۇ",
            "key": "V1001_TODAY_MUSIC"
        },
        {
            "name": "BotFramework",
            "sub_button": [{
                    "type": "view",
                    "name": "botframework",
                    "url": "https://dev.botframework.com/"
                },
                {
                    "type": "click",
                    "name": "赞一下我们",
                    "key": "V1001_GOOD"
                }, {
                    "name": "发送位置",
                    "type": "location_select",
                    "key": "rselfmenu_2_0"
                },
            ]
        }
    ]
}; */
//#endregion